#include <sdl_net.h>

struct sdl_udp_t *sdl_udp_open(const char *ip, unsigned short port, unsigned long buf_size)
{
    struct sdl_udp_t *udp = NULL;

    udp = (struct sdl_udp_t *)malloc(sizeof(struct sdl_udp_t));
    SDL_ERRP(NULL == udp, goto ERR1, 2, "malloc udp");

    udp->packet = SDLNet_AllocPacket(buf_size);
    SDL_ERRP(NULL == udp->packet, goto ERR2, 2, "malloc packet");
    udp->packet->len = 0;

    if (ip != NULL)
    {
        udp->socket = SDLNet_UDP_Open(0);
        SDLNet_ResolveHost(&udp->packet->address, ip, port);
    }
    else
        udp->socket = SDLNet_UDP_Open(port);

    SDL_ERRP(NULL == udp->socket, goto ERR3, 2, "udp open");

    return udp;
ERR3:
    SDLNet_FreePacket(udp->packet);
ERR2:
    free(udp);
ERR1:
    return NULL;
}

void sdl_udp_setconnect(struct sdl_udp_t *udp, IPaddress *ip)
{
    udp->packet->address = *ip;
}

void *sdl_udp_recv(struct sdl_udp_t *udp, int *result)
{
    int ret;

    do
    {
        ret = SDLNet_UDP_Recv(udp->socket, udp->packet); 
        if (ret)
            break;
        SDL_Delay(1);
    } while (!result || *result);

    if (result)
        *result = ret;

    return udp->packet->data;
}

int prepare_data(struct sdl_udp_t *udp, void *data, int size)
{
    memcpy(udp->packet->data + udp->packet->len, data, size);
    udp->packet->len += size;

    return udp->packet->len;
}

int sdl_udp_send(struct sdl_udp_t *udp, void *data, int size)
{
    int ret;

    if (size != 0)
    {
        memcpy(udp->packet->data, data, size); 
        udp->packet->len += size;
    }
    ret = SDLNet_UDP_Send(udp->socket, -1, udp->packet);
    udp->packet->len = 0;

    return ret;
}

int sdl_udp_send_ip(struct sdl_udp_t *udp, IPaddress *ip, void *data, int size)
{
    sdl_udp_setconnect(udp, ip);
    return sdl_udp_send(udp, data, size);
}

void sdl_udp_close(struct sdl_udp_t *udp)
{
    SDLNet_FreePacket(udp->packet);
    SDLNet_UDP_Close(udp->socket);
    free(udp);
}

